/*
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// NOLINTNEXTLINE(readability-function-size)

#ifndef PANDA_VERIFICATION_ABSINT_HANDLE_CONVERSION_GEN_H
#define PANDA_VERIFICATION_ABSINT_HANDLE_CONVERSION_GEN_H

namespace panda::verifier {
%
%
% # =============================================================================================
% # ---------------------------------------------------------------------------------------------
% # stuff to gen CheckBinaryOp and CheckBinaryOp2 funcs
% # ---------------------------------------------------------------------------------------------
% logical_arr = ['And', 'Or', 'Xor', 'Shl', 'Shr', 'Ashr']
% arithm_arr = ['Add', 'Sub', 'Mul', 'Div', 'Mod']
% binary_vreg_arr = ['Andv', 'Orv', 'Xorv', 'Shlv', 'Shrv', 'Ashrv', 'Addv', 'Subv', 'Mulv', 'Divv', 'Modv']
% binary_arr = logical_arr + arithm_arr + binary_vreg_arr
% # ---------------------------------------------------------------------------------------------
%
%
% # ---------------------------------------------------------------------------------------------
% # stuff to gen HandleConversion funcs, not implemeted, CheckBinaryOp, CheckBinaryOp2Imm
% # ---------------------------------------------------------------------------------------------
% handle_conversion_arr = ['I32', 'U32', 'I64', 'U64', 'F32', 'F64']
% first_arg_arr = ['integral32_', 'integral32_', 'integral64_', 'integral64_', 'f32_', 'f64_']
% # ---------------------------------------------------------------------------------------------
%
%
% # ---------------------------------------------------------------------------------------------
% # stuff to gen comparative funcs. Here we keep insts with comparative signatures from isa.yaml
% # ---------------------------------------------------------------------------------------------
% comp_op_arr = ['equal_to','not_equal_to', 'less', 'greater', 'less_equal', 'greater_equal']
% comparative_sig = Array.new()
% # ---------------------------------------------------------------------------------------------
% # =============================================================================================
%
%
%
%
% # =============================================================================================
% # ---------------------------------------------------------------------------------------------
% Panda::instructions.each do |i|
%   if (i.namespace == 'core' || i.namespace == 'ets')
%       mnemonic = i.mnemonic.split('.').map { |p| p == '64' ? 'Wide' : p.capitalize }.join
% # ---------------------------------------------------------------------------------------------
%
%
% # ---------------------------------------------------------------------------------------------
% # gen CheckBinaryOp2 insts
% # ---------------------------------------------------------------------------------------------
%       res_check_binary_op_2 = i.verification.include?('acc_type') && i.verification.include?('v1_type') && !i.verification.include?('branch_target')
%       if res_check_binary_op_2
%           mnemonic = i.mnemonic.split('.').map { |p| p == '64' ? 'Wide' : p.capitalize }.join
%           res_binary_find = res_arithm_find = res_logic_find = false
%           for bin in binary_arr
%               res_binary_find = mnemonic.include?(bin)
%               res_binary_find ? res_arithm_find = arithm_arr.include?(bin) : res_arithm_find = false
%               res_logic_find = res_binary_find ^ res_arithm_find
%               res_binary_find ? break : next
%           end
%           flag_integral = mnemonic.include?('U') || (res_binary_find)
%           flag_float = mnemonic.include?('F')
%           flag_wide = mnemonic.include?('Wide')
%           flag_u = mnemonic.include?('Divu') || mnemonic.include?('Modu')
%           flag_reg = mnemonic.include?('2v')
%           if (!flag_integral) && (!flag_float)
%               call_func_arg = 'i64_, i64_, i32_'
%           elsif flag_float
%               if mnemonic.include?('cmp')
%                   flag_wide ? call_func_arg = 'f64_, f64_, i32_' : call_func_arg = 'f32_, f32_, i32_'
%               else
%                   flag_wide ? call_func_arg = 'f64_, f64_, f64_' : call_func_arg = 'f32_, f32_, f32_'
%               end
%           elsif flag_integral
%               if res_arithm_find && !flag_u
%                   flag_wide ? call_func_arg = 'integral64_, integral64_, i64_' : call_func_arg = 'integral32_, integral32_, i32_'
%               elsif res_logic_find && !flag_u
%                   flag_wide ? call_func_arg = 'integral64_, integral64_' : call_func_arg = 'integral32_, integral32_'
%               elsif mnemonic.include?('cmp')
%                   flag_wide ? call_func_arg = 'integral64_, integral64_, i32_' : call_func_arg = 'integral32_, integral32_, i32_'
%               else
%                   (!flag_wide) ? call_func_arg = 'integral32_, integral32_, u32_' : (flag_u ? call_func_arg = 'integral64_, integral64_, u64_' : call_func_arg = '')
%               end
%           end

    template <BytecodeInstructionSafe::Format FORMAT>
    bool AbsIntInstructionHandler::Handle<%= mnemonic %>()
    {
        LOG_INST();
        DBGBRK();
        Sync();
        return CheckBinaryOp2<FORMAT, <%= flag_reg %>>(<%= call_func_arg %>);
    }
%       end
% # ---------------------------------------------------------------------------------------------
%
%
% # ---------------------------------------------------------------------------------------------
% # gen HandleConversion insts
% # ---------------------------------------------------------------------------------------------
%       for curr_string in handle_conversion_arr
%           if mnemonic.include?(curr_string)
%               index = handle_conversion_arr.index(curr_string)

    template <BytecodeInstructionSafe::Format FORMAT>
    bool AbsIntInstructionHandler::Handle<%= mnemonic %>()
    {
        LOG_INST();
        DBGBRK();
        Sync();
        return HandleConversion<FORMAT>(<%= first_arg_arr[index]%>, <%= mnemonic.split('to')[1]%>_);
    }
%               break
%           end
%       end
% # ---------------------------------------------------------------------------------------------
%
%
% # ---------------------------------------------------------------------------------------------
% # gen not implemented (now .dyn and .ets) inst
% # ---------------------------------------------------------------------------------------------
%       res_not_impl = (mnemonic.include?('Dyn') || mnemonic.include?('Ets')) && !mnemonic.include?('MovDyn') && !mnemonic.include?('Ldobj') && !mnemonic.include?('Stobj')
%       if res_not_impl

    template <BytecodeInstructionSafe::Format FORMAT>
    bool AbsIntInstructionHandler::Handle<%= mnemonic %>()
    {
        LOG_INST();
        DBGBRK();
        Sync();
        LOG(ERROR, VERIFIER) << "Verifier error: instruction is not implemented";
        status_ = VerificationStatus::ERROR;
        return false;
    }
%       end
% # ---------------------------------------------------------------------------------------------
%
%
% # ---------------------------------------------------------------------------------------------
% # gen CheckBinaryOp insts
% # ---------------------------------------------------------------------------------------------
%       for curr_mnemonic in binary_arr
%           if mnemonic == curr_mnemonic

    template <BytecodeInstructionSafe::Format FORMAT>
    bool AbsIntInstructionHandler::Handle<%= mnemonic %>()
    {
        LOG_INST();
        DBGBRK();
        Sync();
        return CheckBinaryOp<FORMAT, <%= binary_vreg_arr.include?(curr_mnemonic) %>>(integral32_, integral32_, i32_);
    }
%               break
%           end
%       end
% # ---------------------------------------------------------------------------------------------
%
%
% # ---------------------------------------------------------------------------------------------
% # gen CheckBinaryOp2Imm insts
% # ---------------------------------------------------------------------------------------------
%       for curr_log in logical_arr
%           if mnemonic == curr_log + 'i'

    template <BytecodeInstructionSafe::Format FORMAT>
    bool AbsIntInstructionHandler::Handle<%= mnemonic %>()
    {
        LOG_INST();
        DBGBRK();
        Sync();
        return CheckBinaryOp2Imm<FORMAT>(integral32_);
    }
%               break
%           elsif mnemonic == (curr_log + 'iv')

    template <BytecodeInstructionSafe::Format FORMAT>
    bool AbsIntInstructionHandler::Handle<%= mnemonic %>()
    {
        LOG_INST();
        DBGBRK();
        Sync();
        return CheckBinaryOpImm<FORMAT>(integral32_, i32_);
    }
%               break
%           end
%       end
%
%       for curr_log in arithm_arr
%           if mnemonic == (curr_log + 'i')

    template <BytecodeInstructionSafe::Format FORMAT>
    bool AbsIntInstructionHandler::Handle<%= mnemonic %>()
    {
        LOG_INST();
        DBGBRK();
        Sync();
        return CheckBinaryOp2Imm<FORMAT>(integral32_, i32_);
    }
%               break
%           elsif mnemonic == (curr_log + 'iv')

    template <BytecodeInstructionSafe::Format FORMAT>
    bool AbsIntInstructionHandler::Handle<%= mnemonic %>()
    {
        LOG_INST();
        DBGBRK();
        Sync();
        return CheckBinaryOpImm<FORMAT>(integral32_, i32_);
    }
%               break
%           end
%       end
% # ---------------------------------------------------------------------------------------------
%
%
% # ---------------------------------------------------------------------------------------------
% # gen HandleCondJmp and HandleCondJmpz insts
% # ---------------------------------------------------------------------------------------------
%       if i.conditional?
%           elem = mnemonic.capitalize
%           if i.verification.include?('v1_type') && !(comparative_sig.include?(elem))
%               comparative_sig.push(elem)

    template <BytecodeInstructionSafe::Format FORMAT>
    bool AbsIntInstructionHandler::Handle<%= elem %>()
    {
        LOG_INST();
        DBGBRK();
        Sync();
        return HandleCondJmp<FORMAT, std::<%=comp_op_arr[comparative_sig.index(elem)]%>>();
    }

    template <BytecodeInstructionSafe::Format FORMAT>
    bool AbsIntInstructionHandler::Handle<%= elem %>z()
    {
        LOG_INST();
        DBGBRK();
        Sync();
        return HandleCondJmpz<FORMAT, std::<%=comp_op_arr[comparative_sig.index(elem)]%>>();
    }
%           end
%       end
% # ---------------------------------------------------------------------------------------------
%   end # end for core namespace
% end # end for Panda::instructions
% # =============================================================================================
}  // namespace panda::verifier

#endif // PANDA_VERIFICATION_ABSINT_HANDLE_CONVERSION_GEN_H